﻿using System;
using System.Collections.Generic;
using Colorful.Furniture.Permissions;
using FreeSql.Internal.Model;
using System.Linq;
using System.Threading.Tasks;
using Colorful.Furniture.Extensions;
using Colorful.Furniture.IEntity;
using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.Users;

namespace Colorful.Furniture.PermissionManagement;

/// <summary>
///  基于角色、个人数据筛选器
/// </summary>
public class RoleAndPersonDataPermissionFilter : IDataPermissionFilter
{
    private readonly IFreeSql _freeSql;
    private readonly ICurrentUser _currentUser;
    private readonly IServiceProvider _serviceProvider;

    /// <summary>
    ///  于角色、个人数据筛选器
    /// </summary>
    public RoleAndPersonDataPermissionFilter(
        IFreeSql freeSql,
        ICurrentUser currentUser,
        IServiceProvider serviceProvider)
    {
        _freeSql = freeSql;
        _currentUser = currentUser;
        _serviceProvider = serviceProvider;
    }

    /// <summary>
    ///  筛选
    /// </summary>
    /// <typeparam name="TFilterMain">主要数据筛选实体类</typeparam>
    /// <returns></returns>
    public async Task<DynamicFilterInfo> FilterAsync<TFilterMain>() where TFilterMain : AuditAggregateRoot, new()
    {
        var dynamicFilter = new DynamicFilterInfo
        {
            Filters = new List<DynamicFilterInfo>()
        };

        //判断是否是超级管理员,是直接查询所有
        var isSupper = await _freeSql.Select<SysManager>()
            .Where(x => x.Id == _currentUser.Id)
            .ToOneAsync(x => x.IsSupper);

        if (isSupper)
            return new DynamicFilterInfo();

        var userIdList = new List<Guid>();

        //通过当前用户查询数据权限
        var managerRoleList = await _freeSql.Select<SysManagerRole>()
            .Where(x => x.ManagerId == _currentUser.Id)
            .ToListAsync(x => new
            {
                x.RoleId,
                x.Role.Name
            });

        var managerRoleIdList = managerRoleList.Select(x => x.RoleId);

        //查询用户拥有数据权限列表
        var userDataPermissionList = await _freeSql.Select<SysDataPermission>()
            .Where(x => x.ManagerId == _currentUser.Id || managerRoleIdList.Contains(x.RoleId))
            .ToListAsync(x => new { x.PermissionType, x.CrossLevelDepart });

        if (userDataPermissionList.Any())
        {
            //获取去重之后的权限列表
            var permissionTypeList = userDataPermissionList
                .Where(x => !string.IsNullOrWhiteSpace(x.PermissionType))
                .SelectMany(x => x.PermissionType.Split(","))
                .Select(x => x.ToInt())
                .Distinct()
                .ToList();

            //如果有一个拥有权限类型为不限，则直接返回查询所有
            if (permissionTypeList.Any(x => x == 0))
            {
                return new DynamicFilterInfo();
            }

            //跨部门列表
            var crossLevelDepartList = userDataPermissionList
                .Where(x=>!string.IsNullOrWhiteSpace(x.CrossLevelDepart))
                .SelectMany(x => x.CrossLevelDepart.Split(","))
                .Select(x => x.ToLong())
                .Distinct()
                .ToList();


            foreach (var dataPermissionProvider in permissionTypeList
                         .Select(permissionType => _serviceProvider.GetServices<IDataPermissionProvider>()
                             .FirstOrDefault(x => x.Type == permissionType)))
            {
                if (dataPermissionProvider == null)
                    return null;

                userIdList.AddRange(await dataPermissionProvider.GetPermissionPointsAsync(new DataPermissionContext { CrossLevelDepartmentIdList = crossLevelDepartList }));
            }
        }

        // ReSharper disable once EntityNameCapturedOnly.Local
        AuditAggregateRoot aggregateRoot;

        //如果没有筛选用户数据，则查询当前自己创建的
        if (userIdList.Any())
        {
            dynamicFilter.Filters.Add(new DynamicFilterInfo
            {
                Field = $"{typeof(TFilterMain).Name}.{nameof(aggregateRoot.AddUserId)}",
                Operator = DynamicFilterOperator.Any,
                Value = userIdList.Distinct()
            });
        }
        else
        {
            dynamicFilter.Filters.Add(new DynamicFilterInfo
            {
                Field = $"{typeof(TFilterMain).Name}.{nameof(aggregateRoot.AddUserId)}",
                Operator = DynamicFilterOperator.Eq,
                Value = _currentUser.Id
            });
        }

        return dynamicFilter;
    }
}